﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;

namespace DAL.Repositories
{
    public class SeatRepository : RepositoryInterfaces.ISeatRepository
    {
        /// <summary>
        /// Change availability of seats, either from taken to free or from free to taken
        /// </summary>
        /// <param name="screenSeats">List of screen cast seat objects</param>
        /// <exception cref="InvalidOperationException">Seat does not exist or save to db failed</exception>
        /// <exception cref="Exception"></exception>
        public void ChangeSeatsAvailability(List<ScreenCast_Seat> screenSeats)
        {
            try
            {
                if (screenSeats != null && screenSeats.Count > 0) // if list is not empty and not null
                {
                    using (BalderEntities _db = new BalderEntities())
                    {
                        foreach (ScreenCast_Seat ss in screenSeats)
                        {
                            if (ss.SeatAvailable != _db.ScreenCast_Seat.Find(ss.Id).SeatAvailable) // if seat in db is different than seat object, save change
                            {
                                _db.ScreenCast_Seat.Find(ss.Id).SeatAvailable = ss.SeatAvailable;
                            }
                            else // else throw exception to tell user seat has been booked/unbooked before
                            {
                                throw new Exception("Seat has been changed before, try again with new seat");
                            }
                        }

                        // If not all seats are changed as they should be, changes won't be saved.
                        _db.SaveChanges();
 
                    }
                }
                else // tell user no seats selected
                {
                    throw new Exception("No seats selected");
                }
            }
            catch (InvalidOperationException ex)
            {
                throw new InvalidOperationException("Seat does not exist, or saving failed!" + Environment.NewLine + ex.Message);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Get seats status object for a screen cast
        /// </summary>
        /// <param name="screenCast">Screen cast to get seats objects from</param>
        /// <returns>List of all screen cast seats</returns>
        /// <exception cref="ArgumentNullException">Screen cast object is null or not existing in db</exception>
        /// <exception cref="Exception"></exception>
        public IList<ScreenCast_Seat> GetScreenCastSeats(ScreenCast screenCast)
        {
            try
            {
                using (BalderEntities _db = new BalderEntities())
                {
                    return _db.ScreenCast_Seat.Include("Seat").Where(sc => sc.ScreenCastId == screenCast.Id).ToList();
                }
            }
            catch (ArgumentNullException ex)
            {
                throw new ArgumentNullException("Screen cast object is null or not existing in db" + Environment.NewLine + ex.Message);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// Get seats by movie hall
        /// </summary>
        /// <param name="movieHall">movie hall object</param>
        /// <returns>List of seats in a movie hall</returns>
        /// <exception cref="ArgumentNullException">Movie hall object is null or not existing in db</exception>
        /// <exception cref="Exception"></exception>
        public IList<Seat> GetSeats(MovieHall movieHall)
        {
            try
            {
                using (BalderEntities _db = new BalderEntities())
                {
                    return _db.Seats.Where(s => s.MovieHallId == movieHall.Id).ToList();
                }
            }
            catch (ArgumentNullException ex)
            {
                throw new ArgumentNullException("Movie hall object is null or not existing in db" + Environment.NewLine + ex.Message);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
